package top.maof.lightsearch.handle;

import org.apache.lucene.document.Document;
import org.apache.lucene.index.IndexableField;
import top.maof.lightsearch.annotation.Property;
import top.maof.lightsearch.converter.Converter;
import top.maof.lightsearch.map.Mapping;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

/**
 * 转化器处理器
 * 处理@Property中带有Converter.class子类的属性
 */

@Handle.Shared
public class ConverterHandle implements Handle {

    @Override
    public void indexHandle(Entity entity, Index index, HandleChain handleChain) throws Exception {

        Iterator<Field> iterator = entity.getFields().iterator();

        while (iterator.hasNext()) {
            Field field = iterator.next();
            Property property = field.getAnnotation(Property.class);

            // 有Converter
            if (property != null && property.convert() != Converter.class) {

                Converter converter = null;

                //获取转换器
                try {
                    converter = property.convert().newInstance();
                    Document document = index.getDocument();
                    String name = handleChain.fieldName(entity.getType().value(), property.value());
                    field.setAccessible(true);
                    Object value = field.get(entity.getT());
                    if (value == null) {
                        continue;
                    }
                    // 索引值
                    Object indexValue = converter.writeCovert(value);
                    // 索引类型
                    Class indexClazz = converter.filedType();
                    Mapping mapping = handleChain.getMapping(indexClazz);
                    if (mapping != null) {
                        Mapping.Parms parms = new Mapping.Parms(indexValue, name, property.isTokenized(), property.isIndexed(), property.isStored());
                        List<IndexableField> indexableFields = mapping.javaMappingIndex(parms);
                        indexableFields.forEach(field1 -> {
                            document.add(field1);
                        });
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // 移除该Field，以防重复操作
                // iterator.remove();
            }
        }

        handleChain.indexHandle(entity, index, handleChain);
    }

    @Override
    public void searchHandle(Entity entity, Index index, HandleChain handleChain) throws Exception {

        Iterator<Field> iterator = entity.getFields().iterator();

        while (iterator.hasNext()) {

            Field field = iterator.next();
            Property property = field.getAnnotation(Property.class);

            // 有Converter
            if (property != null && property.convert() != Converter.class) {

                if (!property.isStored()) {
                    // iterator.remove();
                    continue;
                }
                Converter converter = null;
                //获取转换器
                try {
                    Document document = index.getDocument();
                    String name = handleChain.fieldName(entity.getType().value(), property.value());
                    field.setAccessible(true);
                    converter = property.convert().newInstance();
                    // 索引属性
                    Class indexClazz = converter.filedType();
                    Mapping mapping = handleChain.getMapping(indexClazz);
                    if (mapping != null) {
                        Object indexValue = mapping.indexMappingJava(Arrays.asList(document.getFields(name)));
                        try {
                            field.set(entity.getT(), converter.readCovert(indexValue));
                        } catch (IllegalAccessException e) {
                            e.printStackTrace();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
                // iterator.remove();
            }
        }
        handleChain.searchHandle(entity, index, handleChain);
    }
}
